package com.hooker.base;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public abstract class BaseXposedLoader {

    protected XC_LoadPackage.LoadPackageParam loadParams;
    protected Context context;

    public BaseXposedLoader() {
    }

    public void setLoadParams(XC_LoadPackage.LoadPackageParam loadParams) {
        this.loadParams = loadParams;
    }

    public void setContext(Context context) {
        this.context = context;
    }

    public BaseXposedLoader(Context context, XC_LoadPackage.LoadPackageParam loadParams) {
        this.loadParams = loadParams;
        this.context = context;
    }

    /**
     * hook插件的入口
     *
     * @param context
     * @param loadParams
     */
    public void hook(Context context, XC_LoadPackage.LoadPackageParam loadParams) {
        hook();
    }

    public abstract void hook(Object... calls);

    protected void log(String msg) {
        Log.d("Hooker", msg);
    }

    protected void logE(String msg) {
        Log.e("Hooker", msg);
    }

    public void hookMethod(String className, String method, Object... parameterTypesAndCallback) {
        try {
            if (loadParams != null) {
                XposedHelpers.findAndHookMethod(className, loadParams.classLoader, method, parameterTypesAndCallback);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void hookMethod(Class cls, ClassLoader loader, String method, Object... parameterTypesAndCallback) {
        hookMethod(cls.getName(), loader, method, parameterTypesAndCallback);
    }

    public void hookMethod(String className, ClassLoader loader, String method, Object... parameterTypesAndCallback) {
        try {
            if (loadParams != null) {
                XposedHelpers.findAndHookMethod(className, loader, method, parameterTypesAndCallback);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void hookMethod(Class cls, String method, Object... parameterTypesAndCallback) {
        if (cls != null) {
            hookMethod(cls.getName(), method, parameterTypesAndCallback);
        }
    }

    public void hookAllMethod(Class cls, String method, XC_MethodHook xc_methodHook) {
        try {
            if (loadParams != null) {
                Class packCls = loadParams.classLoader.loadClass(cls.getName());
                XposedBridge.hookAllMethods(packCls, method, xc_methodHook);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void hookConstructor(String className, Object... parameterTypesAndCallback) {
        try {
            if (loadParams != null) {
                XposedHelpers.findAndHookConstructor(className, loadParams.classLoader, parameterTypesAndCallback);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void hookConstructor(String className, ClassLoader loader, Object... parameterTypesAndCallback) {
        try {
            if (loadParams != null) {
                XposedHelpers.findAndHookConstructor(className, loader, parameterTypesAndCallback);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void hookConstructor(Class cls, Object... parameterTypesAndCallback) {
        try {
            if (loadParams != null) {
                Class className = loadParams.classLoader.loadClass(cls.getName());
                XposedHelpers.findAndHookConstructor(className, parameterTypesAndCallback);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void hookAllConstructor(Class cls, XC_MethodHook xc_methodHook) {
        try {
            if (loadParams != null) {
                cls = loadParams.classLoader.loadClass(cls.getName());
                XposedBridge.hookAllConstructors(cls, xc_methodHook);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void hookAllConstructor(String className, XC_MethodHook xc_methodHook) {
        try {
            if (loadParams != null) {
                Class cls = loadParams.classLoader.loadClass(className);
                XposedBridge.hookAllConstructors(cls, xc_methodHook);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
